package com.ywu.application.standard.thirdExec.exec.impl;

import com.ywu.file.sys.sdk.enter.YwuFileSysExec;
import com.ywu.application.standard.thirdExec.entity.YwuThirdExecEntity;
import com.ywu.application.standard.thirdExec.exec.YwuThirdExecEngine;
import com.ywu.application.standard.thirdExec.exec.param.ParamParseCoreService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @ClassName YwuJavaScriptExecEngine
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/10/14 11:16
 * @Version 1.0
 **/
@Component
@Slf4j
public class YwuJavaScriptExecEngine implements YwuThirdExecEngine {

    @Autowired
    private YwuFileSysExec ywuFileSysExec;

    @Autowired
    private ParamParseCoreService paramParseCoreService;

    private static final String JAVA_SCRIPT_ENGINE_TYPE = "JavaScript";

    /**
    * @Author GroundDemo
    * @Description 执行类型
    * @Date 9:03 2024/10/16
    * @Param []
    * @return java.lang.String
    **/
    @Override
    public String execType() {
        return JAVA_SCRIPT_ENGINE_TYPE;
    }

    /**
    * @Author GroundDemo
    * @Description 执行核心逻辑
    * @Date 9:03 2024/10/16
    * @Param [entity]
    * @return java.lang.Object
    **/
    @Override
    public Object exec(YwuThirdExecEntity entity) {
        // 解析参数
        Map<String, Object> paramMap = paramParseCoreService.parseThirdExecParam(entity);
        // 下载文件
        String filePath = downloadThirdFile(entity, ywuFileSysExec);
        // 获取核心方法的参数列表
        List<String> functionParamList = getFunctionParamList(filePath);
        if (Objects.isNull(functionParamList)) {
            log.error("function param parse error");
            File file = new File(filePath);
            file.delete();
            return null;
        }
        // 根据参数列表的名称，获取对应的入参值列表
        List<Object> inputParams = getInputParamList(functionParamList, paramMap);
        // 获取JS脚本引擎管理器
        ScriptEngineManager manager = new ScriptEngineManager();
        // 获取JS的执行引擎
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        // 存储执行结果
        Object result = null;
        // 加载对应的脚本
        try(InputStream in = new FileInputStream(filePath)) {
            engine.eval(new InputStreamReader(in, StandardCharsets.UTF_8));
            // 动态调用函数并获取返回后的数据
            Invocable invocable = (Invocable) engine;
            result = invocable.invokeFunction("handlerCoreService", inputParams.toArray());
        } catch (ScriptException | NoSuchMethodException | IOException e) {
            log.error("JavaScript Exec Error {}", e.getMessage());
            result = "JavaScript Exec Error " + e.getMessage();
        } finally {
            File file = new File(filePath);
            // 删除下载的文件
            file.delete();
        }
        return result;
    }

    /**
    * @Author GroundDemo
    * @Description 根据方法参数的值或者对应的入参信息
    * @Date 9:31 2024/10/18
    * @Param [functionParamList, paramMap]
    * @return java.util.List<java.lang.Object>
    **/
    private List<Object> getInputParamList(List<String> functionParamList, Map<String, Object> paramMap) {
        List<Object> res = new ArrayList<>();
        for (String paramName : functionParamList) {
            res.add(paramMap.getOrDefault(paramName, null));
        }
        return res;
    }

    /**
    * @Author GroundDemo
    * @Description 读取js文件内容，获取核心方法中的参数
    * @Date 9:15 2024/10/18
    * @Param [filePath]
    * @return void
    **/
    private List<String> getFunctionParamList(String filePath) {
        String coreServiceStr = "function handlerCoreService(";
        String coreFunctionContentLine = "";
        try(BufferedReader in = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = in.readLine()) != null) {
                if (StringUtils.contains(line, coreServiceStr)) {
                    coreFunctionContentLine = line;
                    break;
                }
            }
        } catch (IOException e) {
            log.error("exec JavaScript IO Exception {}", e.getMessage());
            return null;
        }
        if (StringUtils.isEmpty(coreFunctionContentLine)) {
            log.error("coreFunctionContentLine is empty");
            return null;
        }
        int start = coreFunctionContentLine.indexOf(coreServiceStr);
        int end = coreFunctionContentLine.indexOf(")", start + 1);
        String paramStr = coreFunctionContentLine.substring(start + coreServiceStr.length(), end);
        StringBuilder stringBuilder = new StringBuilder();
        // 去除所有的空格
        for (int i = 0; i < paramStr.length(); i++) {
            char c = paramStr.charAt(i);
            if (c != ' ') {
                stringBuilder.append(c);
            }
        }
        // 根据逗号分割数据
        String[] paramArr = stringBuilder.toString().split(",");
        return Arrays.asList(paramArr);
    }
}
